
//
// 120613 - AH - Created.
// 120708 - AH - Fixed so do not ask the orb about the engine name before after
//               let basic suppliers supply (one of those may be the one 
//               providing the name).
//

package org.soekrat.environment;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *   Organizes 
 *   {@link OrbSupplier}s.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class OrbSuppliers 
{
  private final List<OrbSupplier> m_basicSuppliers=
    new ArrayList<OrbSupplier>();
  
  private final Map<String, List<OrbSupplier>> m_suppliers=
    new HashMap<String, List<OrbSupplier>>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   */
  public OrbSuppliers(){}
  
  /**
   * <p>
   *   Supply an
   *   {@link Orb} to be ready for its conversation environment.
   * </p>
   * @param orb {@code Orb} to supply.
   * @return Error message or {@code null} if OK.
   */
  public String supply(Orb orb)
  {
    if (orb==null)
    {
      throw new NullPointerException("orb");
    }
   
    List<OrbSupplier> secondPass=new ArrayList<OrbSupplier>();
    
    for (OrbSupplier os : m_basicSuppliers)
    {
      String err=os.supply(orb, secondPass);
      if (err!=null) return err;
    }
    
    String engineName=orb.getString("engine");
    if (engineName==null)
    {
      return "OrbSuppliers: Orb is missing engine name";
    }
     
    List<OrbSupplier> suppliers=m_suppliers.get(engineName);
    if (suppliers==null)
    {
      return "OrbSuppliers: Unknown engine : "+engineName;
    }
    
    for (OrbSupplier os : suppliers)
    {
      String err=os.supply(orb, secondPass);
      if (err!=null) return err;
    }
    
    for (OrbSupplier os : secondPass)
    {
      String err=os.supply(orb, secondPass);
      if (err!=null) return err;
    }
    
    return null;
  }
  
  /**
   * <p>
   *   Adds 
   *   {@link OrbSupplier}.
   * </p>
   * @param oi {@code OrbSupplier} to add.
   * @return {@code this}.
   */
  public OrbSuppliers addSupplier(OrbSupplier oi)
  {
    if (oi==null)
    {
      throw new NullPointerException("orb");
    }
    
    String engineName=oi.getEngineName();
    
    if (engineName==null)
    {
       m_basicSuppliers.add(oi);
    }
    else
    {
      List<OrbSupplier> inits=m_suppliers.get(engineName);
      if (inits==null)
      {
        inits=new ArrayList<OrbSupplier>();
        m_suppliers.put(engineName, inits);
      }
      if (!inits.contains(oi)) inits.add(oi);
    }
    
    return this;
  }
  
  @Override
  public String toString() 
  {
    CharArrayWriter caw=new CharArrayWriter();
    PrintWriter pw=new PrintWriter(caw);
    
    pw.println("Suppliers for all engines and conversation environments:");
    pw.println();
    for (OrbSupplier curr : m_basicSuppliers)
    {
      pw.println(curr.getClass().getName());  
    }
    
    for (Map.Entry<String, List<OrbSupplier>> entry : m_suppliers.entrySet())
    {
      pw.println("Suppliers for engine "+entry.getKey());
      pw.println();
      for (OrbSupplier curr : entry.getValue())
      {
        pw.println(curr.getClass().getName());  
      }  
    }
    
    pw.flush();
    return caw.toString();
  }
  
}
